/* ********************************************************************* */
/*                                                                       */
/*                       Librairies de IP                                */
/*                                                                       */
/* ********************************************************************* */

#include "IP.h"


/* ********************************************************************* */
/*                                                                       */
/*                        Les Fonctions                                  */
/*                                                                       */
/* ********************************************************************* */


void initIP(IP * ip, const int  codeIp, const int codeUe, const int numEtu, const int  annee,const char semestre, const char groupe)
{
    assert(ip != NULL);
    setCodeIp(ip,codeIp);
    setUE_IP(ip, codeUe);
    setEtu_IP(ip,numEtu);
    setAnnee_IP(ip, annee);
    setSemestre(ip, semestre);
    setGroupe(ip, groupe);
}

void libIP(IP * ip)
{
    assert(ip!=NULL);
    ip->codeIp=0;
    ip->codeUe=0;
    ip->numEtu=0;
    ip->annee=0;
    ip->semestre = 0;
    ip->groupe   = 0;
}

IP * creIP(const int  codeIp,const int  codeUe, const int  numEtu, const int  annee,const char semestre, const char groupe)
{
    IP *ip = (IP *) calloc(1,sizeof(IP));
    initIP(ip,codeIp,codeUe, numEtu, annee, semestre, groupe);

    return ip ;
}

void detIP(IP ** ip)
{
    assert(*ip != NULL);

    libIP(*ip);
    free(*ip);
    *ip = NULL ;
}


/* ******************************************************************** */
/*																		*/
/*           Accesseurs et Mutateurs de la structure UE                 */
/*																		*/
/* ******************************************************************** */

int  getUE_IP(const IP * ip)
{
    if(ip && (ip->codeUe!=0))
        return ip->codeUe;
    else
        return -1;
}


void setCodeIp(IP*ip,const int codeIp)
{
    assert(ip!=NULL);
    ip->codeIp=codeIp;
}



void setUE_IP(IP * ip,const int  codeUe)
{
    /*assert(ue!=NULL);*/
    if(codeUe>0)
    {
        if(ip);
        ip->codeUe=codeUe;
    }
}

int  getEtu_IP(const IP * ip)
{
    if(ip && (ip->numEtu!=0))
        return ip->numEtu;
    else
        return -1;
}

void setEtu_IP(IP * ip,const int numEtu)
{
    if(numEtu>0)
    {
        if(ip);
        ip->numEtu=numEtu;
    }
}

int  getAnnee_IP(const IP * ip)
{
    if(ip && (ip->annee!=0))
        return ip->annee;
    else
        return -1;
}

void setAnnee_IP(IP * ip,const int  annee)
{
    if(annee>0)
    {
        if(ip);
        ip->annee=annee;
    }
}

char getSemestre(const IP * ip)
{
    /*if(ip && (ip->semestre==Automne || ip->semestre==Printemps))*/
    if(ip)
        return ip->semestre;
    else
        return '0';
}

void setSemestre(IP * ip,const char semestre)
{
    /*if(semestre && (semestre==Automne || semestre==Printemps))*/
    int i_sem=semestre-48;
    if(i_sem==1 || i_sem==2)
    {
        if(ip);
        ip->semestre = semestre;
    }
        else
    {
        ip->semestre='0';
    }
}

char getGroupe(const IP * ip)
{
    if(ip)
        return ip->groupe;
    else
        return 0;
}

void setGroupe(IP * ip,const char groupe)
{
    if(groupe)
    {
        if(ip);
        ip->groupe= groupe;
    }
}

void affIP(const IP * ip)
{
    if(ip!=NULL && ip->codeUe!=0 && ip->numEtu!=0 && ip->annee)
    {
        affEtu(recEtuParCode(ip->numEtu));
        printf("Code Ip:%d\n",ip->codeIp);
        affUE(recUEParCode(ip->codeUe));
        printf("Année:       %d\n" , ip->annee);
        int sem=ip->semestre-48;
        switch (sem)
        {
            case 1 :
                printf("semestre:    Automne\n");
                break;

            case 2:
                printf("semestre:    Printemps\n");
                break;

            default :
                printf("semestre:    aucun !!\n");
                break;
        }
        printf("Groupe:      %c\n" , ip->groupe);
    }
    else
    {
        printf("\nAucun IP!!");
    }
}
/* ********************************************************************* */
/*                                                                       */
/*             Fonctions relatives aux gestiond'Etu                       */
/*                                                                       */
/* ********************************************************************* */


void  saveIp(IP*ip)
{
    assert(ip!=NULL && ip->codeIp>0   &&  ip->codeUe>0  &&    ip->numEtu>0    &&  ip->annee>0 );
    savIPParElem(ip->codeIp,ip->codeUe,ip->numEtu,ip->annee,ip->semestre,ip->groupe);
}


void savIPParElem(const int codeIp,const int codeUe,const int numEtu,const int  annee,
                  const char semestre, const char groupe)
{
    FILE* f;

    f = fopen(IP_DB, "a");

    if (f==NULL)
    {
        printf("Erreur lors de l'ouverture de %s\n", IP_DB);
        exit(EXIT_FAILURE);
    }
    fclose(f);
    if(recIpParCodeUeNumEtu(numEtu,codeUe)==NULL)
    {
        f = fopen(IP_DB, "a");

        char*c_codeIp=calloc(20,sizeof(char));
        char*c_codeUe=calloc(20,sizeof(char));
        char*c_numEtu=calloc(20,sizeof(char));
        char*c_annee=calloc(20,sizeof(char));
        sprintf(c_codeUe,"%d",codeUe);
        sprintf(c_codeIp,"%d",codeIp);
        sprintf(c_numEtu,"%d",numEtu);
        sprintf(c_annee,"%d",annee);
        char*c_semestre=calloc(1,sizeof(char));
        sprintf(c_semestre,"%c",semestre);
        char*c_groupe=calloc(1,sizeof(char));
        sprintf(c_groupe,"%c",groupe);
        char*chaine=calloc(100,sizeof(char));

        strcat(chaine,c_codeIp);
        strcat(chaine,":");
        strcat(chaine,c_codeUe);
        strcat(chaine,":");
        strcat(chaine,c_numEtu);
        strcat(chaine,":");
        strcat(chaine,c_annee);
        strcat(chaine,":");
        strcat(chaine,c_semestre);
        strcat(chaine,":");
        strcat(chaine,c_groupe);
        strcat(chaine,"\n");

        fputs(chaine, f);
        fclose(f);


        free(c_codeIp);
        free(c_codeUe);
        free(c_numEtu);
        free(c_annee);
        free(c_groupe);
        free(c_semestre);
        free(chaine);
    }
    /* TODO (salah#1#): Ecrire dans un fichier les information sur une Ip
    ne pas oublier de rajouter une fonction qui liste toutes les ip d'un etudiant(numEtu) et une qui liste tout les etudiants insrit a la meme ue(codeue) */
    else
    {
        printf("Deja  inscrit a cette UE !!!!!\n");
    }
}

IP* recIpParCodeUeNumEtu(int  numEtu,int  codeUe)
{
    FILE* f;

    f = fopen(IP_DB, "r");

    if (f==NULL)
    {
        printf("Erreur lors de l'ouverture de %s\n", IP_DB);
        exit(EXIT_FAILURE);
    }
    char*contenu=calloc(100,sizeof(char));
    while(fgets(contenu,100,f) != NULL)
    {
        char**tabor=g_strsplit((gchar*)contenu,(gchar*)"\n",100);
        char**tab=g_strsplit((gchar*)tabor[0],(gchar*)":",100);
        if(numEtu==atoi(tab[2])  &&  codeUe==atoi(tab[1]))
        {
            char    sem=(char)*tab[4];
            char    grp=(char)*tab[5];
            fclose(f);
            return  creIP(atoi(tab[0]),atoi(tab[1]),atoi(tab[2]),atoi(tab[3]),sem,grp);
        }
        free(tabor);
        free(tab);
    }
    free(contenu);

    if(!feof(f))
        printf("autre probleme \n");

    fclose(f);

    return NULL;
}

TabIP* rchIPParUe(UE*ue)
{
    assert(ue!=NULL);
    return  rchIPParCodeUe(ue->codeUE);
}


TabIP* rchIPParCodeUe(const int codeUE)
{
    FILE* f;
    int i=1;
    IP **ip=calloc(i,sizeof(IP));

    f = fopen(IP_DB, "r");

    if (f==NULL)
    {
        printf("Erreur lors de l'ouverture de %s\n",IP_DB);
        exit(EXIT_FAILURE);
    }
    char*contenu=calloc(100,sizeof(char));
    while(fgets(contenu,100,f) != NULL)
    {
        char**tabor=g_strsplit((gchar*)contenu,(gchar*)"\n",100);
        char**tab=g_strsplit((gchar*)tabor[0],(gchar*)":",100);
        if(codeUE==atoi(tab[1]))
        {
            ip=realloc(ip,sizeof(IP)*i);
            char    sem=(char)*tab[4];
            char    grp=(char)*tab[5];
            ip[i-1]=creIP(atoi(tab[0]),atoi(tab[1]),atoi(tab[2]),atoi(tab[3]),sem,grp);
            i++;

        }
        free(tabor);
        free(tab);
    }
    free(contenu);

    if(!feof(f))
        printf("autre probleme \n");

    fclose(f);
    TabIP*tabIP=calloc(1,sizeof(TabIP));
    tabIP->tabIp=ip;
    tabIP->nbIP=i-1;
    return tabIP;
}

IP* rchIPParCode(const int codeIp)
{
    FILE* f;

    f = fopen(IP_DB, "r");

    if (f==NULL)
    {
        return  NULL;
    }

    char*contenu=calloc(100,sizeof(char));
    while(fgets(contenu,100,f) != NULL)
    {
        char**tabor=g_strsplit((gchar*)contenu,(gchar*)"\n",100);
        char**tab=g_strsplit((gchar*)tabor[0],(gchar*)":",100);
        if(codeIp==atoi(tab[0]))
        {

            char    sem=(char)*tab[4];
            char    grp=(char)*tab[5];
            fclose(f);
            return  creIP(atoi(tab[0]),atoi(tab[1]),atoi(tab[2]),atoi(tab[3]),sem,grp);
        }
        free(tabor);
        free(tab);
    }
    free(contenu);
    if(!feof(f))
        printf("autre probleme \n");

    fclose(f);

    return NULL;
}

void affIP_DB()
{
    FILE* f;
    IP *ip;

    f = fopen(IP_DB, "r");

    if (f==NULL)
    {
        printf("Erreur lors de l'ouverture de %s\n", IP_DB);
        exit(EXIT_FAILURE);
    }
    char*contenu=calloc(100,sizeof(char));
    while(fgets(contenu,100,f)!=NULL)
    {
        char**tabor=g_strsplit((gchar*)contenu,(gchar*)"\n",100);
        char**tab=g_strsplit((gchar*)tabor[0],(gchar*)":",100);

        char    sem=(char)*tab[4];
        char    grp=(char)*tab[5];
        ip=creIP(atoi(tab[0]),atoi(tab[1]),atoi(tab[2]),atoi(tab[3]),sem,grp);
        affIP(ip);
        detIP(&ip);

        free(tabor);
        free(tab);
    }
    free(contenu);
    if(!feof(f))
        printf("autre probleme \n");
    fclose(f);
}


int supIp(IP*ip)
{
    assert(ip!=NULL);
    assert(ip->codeIp>0);

    return  supprimeIPParCode(ip->codeIp);
}

/* ********************************************************************* */
int supprimeIPParCode(int codeIp)
{
    char *contenu=calloc(100,sizeof(char));
    FILE * fIn;
    FILE * fOut;

    if ((fIn = fopen(IP_DB, "r")) == NULL)
        return EXIT_FAILURE;

    if ((fOut = fopen("texte.tmp", "w")) == NULL)
    {
        fclose(fIn);
        return EXIT_FAILURE;
    }

    while (fgets(contenu,100, fIn))
    {
        char * ligne=calloc(100,sizeof(char));
        copStr(&ligne,contenu);
        char**tabor=g_strsplit((gchar*)contenu,(gchar*)"\n",100);
        char**tab=g_strsplit((gchar*)tabor[0],(gchar*)":",100);
        if (atoi(tab[0]) != codeIp)
            fputs(ligne, fOut);
        free(tabor);
        free(tab);
    }
    free(contenu);

    fclose(fIn);
    fclose(fOut);

    rename("texte.tmp", IP_DB);
    return 0;
}

int supprimeIPParNumEtuUE(int numEtu,int codeUe )
{
    char *contenu=calloc(100,sizeof(char));
    FILE * fIn;
    FILE * fOut;

    if ((fIn = fopen(IP_DB, "r")) == NULL)
        return EXIT_FAILURE;

    if ((fOut = fopen("texte.tmp", "w")) == NULL)
    {
        fclose(fIn);
        return EXIT_FAILURE;
    }

    while (fgets(contenu,100, fIn))
    {
        char * ligne=calloc(100,sizeof(char));
        copStr(&ligne,contenu);
        char**tabor=g_strsplit((gchar*)contenu,(gchar*)"\n",100);
        char**tab=g_strsplit((gchar*)tabor[0],(gchar*)":",100);
        if (atoi(tab[1]) != numEtu  &&  atoi(tab[2]) !=codeUe)
            fputs(ligne, fOut);
        free(ligne);
        free(tabor);
        free(tab);
    }

    free(contenu);
    fclose(fIn);
    fclose(fOut);

    rename("texte.tmp", IP_DB);
    return 0;
}

/** @brief recEtuInscritParCodeUe
  *
  * @todo: document this function
  */
TabEtu* recEtuInscritParCodeUe(int codeUe)
{
    FILE* f;
    int i=1;
    Etu **etus=calloc(i,sizeof(Etu));

    f = fopen(IP_DB, "r");

    if (f==NULL)
    {
        printf("Erreur lors de l'ouverture de %s\n", IP_DB);
        exit(EXIT_FAILURE);
    }
    char*contenu=calloc(100,sizeof(char));
    while(fgets(contenu,100,f) != NULL)
    {
        char**tabor=g_strsplit((gchar*)contenu,(gchar*)"\n",100);
        char**tab=g_strsplit((gchar*)tabor[0],(gchar*)":",100);
        if(codeUe==atoi(tab[1]))
        {
            etus=realloc(etus,sizeof(Etu)*i);

            etus[i-1]=recEtuParCode(atoi(tab[2]));
            i++;
        }
        free(tabor);
        free(tab);
    }
    free(contenu);
    if(!feof(f))
        printf("autre probleme \n");

    fclose(f);
    TabEtu*tabEtu=calloc(1,sizeof(TabIP));
    tabEtu->tabEtu=etus;
    tabEtu->nbEtu=i-1;
    return tabEtu;
    }

/** @brief recEtuInscritParUe
  *
  * @todo: document this function
  */
TabEtu* recEtuInscritParUe(UE*ue)
    {
    return  recEtuInscritParCodeUe(ue->codeUE);
    }


int getNewCodeIp()
{
    int i=1;

    while(rchIPParCode(i)!=NULL)
    {
        i++;
    }
    return  i;
}

void  detTabIp(TabIP**tabIp)
{
    (*tabIp)->nbIP=0;
    free((*tabIp)->tabIp);
    free(*tabIp);
}

/** @brief recUeParIp
  *
  * @todo: document this function
  */
UE* recUeParIp(IP*ip)
{
    UE *ue=recUEParCode(ip->codeUe);
    if(ue!=NULL)
    {
        return  ue;
    }
    else
    {
        printf("Impossible  de  trouver une ue  portant cet identifiant dans la base de donnee!!!\n");
        return  NULL;
    }
}


TabUe* recUeParEtu(Etu*etu)
{
    assert(etu!=NULL    &&  etu->numEtu>0);
    return  recUeParNumEtu(etu->numEtu);
}

/** @brief recUeParEtu
  *
  * @todo: document this function
  */
TabUe* recUeParNumEtu(int  numEtu)
{
    TabIP*tabIp=recIpParNumEtudiant(numEtu);
    TabUe*tabUe=calloc(1,sizeof(TabUe));
    UE**ues=calloc(tabIp->nbIP,sizeof(UE));
    int i=0;

    while(i<tabIp->nbIP)
    {
        IP  *ip=tabIp->tabIp[i];
        ues[i]=recUEParCode(ip->codeUe);
        i++;
    }

    detTabIp(&tabIp);


    tabUe->tabUe=ues;
    tabUe->nbUe=i;
    return  tabUe;
}

TabIP* recIpParEtudiant(Etu* etu)
{
    assert(etu!=NULL);
    assert(etu->numEtu>0);
    return  recIpParNumEtudiant(etu->numEtu);
}

/** @brief recIpParEtudiant
  *
  * @todo: document this function
  */
TabIP* recIpParNumEtudiant(int numEtu)
{

    FILE* f;
    int i=1;
    IP **ips=calloc(i,sizeof(IP));

    f = fopen(IP_DB, "r");

    if (f==NULL)
    {
        printf("Erreur lors de l'ouverture de %s\n", IP_DB);
        exit(EXIT_FAILURE);
    }
    char*contenu=calloc(100,sizeof(char));

    while(fgets(contenu,100,f) != NULL)
    {
        char**tabor=g_strsplit((gchar*)contenu,(gchar*)"\n",100);
        char**tab=g_strsplit((gchar*)tabor[0],(gchar*)":",100);
        if(numEtu==atoi(tab[2]))
        {
            ips=realloc(ips,sizeof(IP)*i);
            char    sem=(char)*tab[4];
            char    grp=(char)*tab[5];

            ips[i-1]=creIP(atoi(tab[0]),atoi(tab[1]),atoi(tab[2]),atoi(tab[3]),sem,grp);

            i++;
        }
        free(tabor);
        free(tab);
    }
    free(contenu);

    if(!feof(f))
        printf("autre probleme \n");

    fclose(f);
    TabIP*tabIp=calloc(1,sizeof(TabIP));
    tabIp->tabIp=ips;
    tabIp->nbIP=i-1;
    return tabIp;
}

/** @brief modifierIp
  *
  * @todo: document this function
  */
int modifierIp(IP*ip,IP*ipnew)
{
    assert(ip!=NULL &&  ipnew!=NULL);
    supIp(ip);
    saveIp(ipnew);

    return  0;
}

/** @brief definitAutomatiquementGroupe
  *
  * @todo: document this function
  */
int definitAutomatiquementGroupe(UE*ue,int  nbGroupe)
{
    assert(ue!=NULL &&  nbGroupe>0);
    TabIP  *tabIp=rchIPParCodeUe(ue->codeUE);
    if(tabIp!=NULL  &&  tabIp->nbIP>0)
    {
        if(nbGroupe>tabIp->nbIP){nbGroupe=tabIp->nbIP;}
        int nbElveParGroupe=  (int)  ((tabIp->nbIP/nbGroupe));
        int i=0;
        int j=0;
        int cpt=0;
        while(i<tabIp->nbIP)
        {
            while(j<nbGroupe-1)
            {
                cpt=0;
                while(cpt<nbElveParGroupe)
                {
                    setGroupe(tabIp->tabIp[i],'A'+j);
                    i++;
                    cpt++;
                }
                j++;
            }
            setGroupe(tabIp->tabIp[i],'A'+j);
            i++;
        }
        i=0;
        while(i<tabIp->nbIP)
        {
            modifierIp(tabIp->tabIp[i],tabIp->tabIp[i]);
            i++;
        }

    }
    else
    {
        printf("Erreur: aucun   etudiant    inscrit à   l'ue    ou  ue  invalide!!!\n");
        return  -1;
    }
    return  0;
}

int getNbGroupeUe(UE *ue)
{
    TabIP *tabIp=rchIPParUe(ue);
    int i=0;
    if(tabIp==NULL) return 0;
    int gr=0;
    while(i<tabIp->nbIP)
    {

    char*c_gr=calloc(1,sizeof(char));
    sprintf(c_gr,"%c",tabIp->tabIp[i]->groupe);
    if(strcmp(c_gr,"X")!=0)
    {
    int a=tabIp->tabIp[i]->groupe;
    if(a>gr)
    {
        gr=a;
    }
    }
    free(c_gr);
    c_gr=NULL;
    i++;
    }
    if(gr!=0)
       {
    gr=gr-64;
       }
       return gr;
}

void regIP()
{

}


